//总结：实验--环境变量的实验内容
#include<iostream>
#include<string>
#include<unistd.h>
#include<pthread.h>

//定义一个函数指针（typedef 是另一种创建函数指针的方法）—typedef  返回类型(*新类型)(参数表)
//定义了一个func_t的类型，该类型指向函数的指针，并void作为返回类型
#define TNUM 4
//线程名，锁名，条件变量名
typedef void (*func_t)(const std::string &name,pthread_mutex_t*pmtx,pthread_cond_t*pcond);
//声明一个可能被多线程使用的变量
volatile bool quit = false;

//用来产生多个线程，名字、方法、锁、条件变量
class ThreadData
{
    public:
        ThreadData(const std::string &name,func_t func,pthread_mutex_t *pmtx,pthread_cond_t*pcond)
        :name_(name),func_(func),pmtx_(pmtx),pcond_(pcond)
        {}
    public:
        std::string name_;
        func_t func_;
        pthread_mutex_t *pmtx_;
        pthread_cond_t *pcond_;
};

//创建四种进程的执行方法
void func1(const std::string &name,pthread_mutex_t *pmtx,pthread_cond_t*pcond)
{
    //wait：线程等待一定是在线程加锁和解锁中间进行的
    pthread_mutex_lock(pmtx);
    //重点理解：第二个参数，wait执行的时候，会让当前线程先阻塞等待
    pthread_cond_wait(pcond,pmtx);
    std::cout<<name<<"任务1"<<std::endl;
    pthread_mutex_unlock(pmtx);
}

void func2(const std::string &name,pthread_mutex_t *pmtx,pthread_cond_t*pcond)
{
    //wait：线程等待一定是在线程加锁和解锁中间进行的
    pthread_mutex_lock(pmtx);
    //重点理解：第二个参数，wait执行的时候，会让当前线程先阻塞等待
    pthread_cond_wait(pcond,pmtx);
    std::cout<<name<<"任务2"<<std::endl;
    pthread_mutex_unlock(pmtx);
    
}

void func3(const std::string &name,pthread_mutex_t *pmtx,pthread_cond_t*pcond)
{
    //wait：线程等待一定是在线程加锁和解锁中间进行的
    pthread_mutex_lock(pmtx);
    //重点理解：第二个参数，wait执行的时候，会让当前线程先阻塞等待
    pthread_cond_wait(pcond,pmtx);
    std::cout<<name<<"任务3"<<std::endl;
    pthread_mutex_unlock(pmtx);
}

void func4(const std::string &name,pthread_mutex_t *pmtx,pthread_cond_t*pcond)
{
     //wait：线程等待一定是在线程加锁和解锁中间进行的
    pthread_mutex_lock(pmtx);
    //重点理解：第二个参数，wait执行的时候，会让当前线程先阻塞等待
    pthread_cond_wait(pcond,pmtx);
    std::cout<<name<<"任务4"<<std::endl;
    pthread_mutex_unlock(pmtx);
}

//封装线程启动后运行的函数
void *Entry(void*args)
{
    //td标记每个线程在栈中属于自己的空间,并利用其运行创建函数和执行相应功能
    ThreadData*td = (ThreadData*)args;
    td->func_(td->name_,td->pmtx_,td->pcond_);
    delete td;
    return nullptr;
}


int main()
{
    //创建锁和条件变量，并初始化
    pthread_mutex_t mtx;
    pthread_cond_t cond;
    pthread_mutex_init(&mtx,nullptr);
    pthread_cond_init(&cond,nullptr);

    //创建多个线程，同时将其功能进行封装
    pthread_t tids[TNUM];
    func_t funcs[TNUM] = {func1,func2,func3,func4};
    for(int i =0;i<TNUM;i++)
    {
        std::string name = "Thread";
        name += std::to_string(i+1);
        ThreadData*td = new ThreadData(name,funcs[i],&mtx,&cond);
        pthread_create(tids+i,nullptr,Entry,(void*)td);
    }

    sleep(5);

    int cnt = 10;
    while(cnt)
    {
        std::cout<<"resume thread run code ..."<<cnt--<<std::endl;
        //唤醒等待
        pthread_cond_signal(&cond);
        sleep(1);
    }

    //线程执行完毕，改变其状态
    std::cout<<"ctrl done"<<std::endl;
    quit = true;
    pthread_cond_broadcast(&cond);

    //回收4个线程，并标记回收信息
    for(int i = 0;i<TNUM;i++)
    {
        pthread_join(tids[i],nullptr);
        std::cout<<"Thread:"<<tids[i]<<quit<<std::endl;
    }

    //销毁锁和环境变量
    pthread_mutex_destroy(&mtx);
    pthread_cond_destroy(&cond);
    return 0;
}